#include "Module/Module.h"
#include "ModuleIOPortManager/ModuleIOPortManager.h"
#include <memory>


APP_ERROR Module::Start(bool getFPS) {
    status_ = RunMode::RUNNING;
    auto ret = Init();
    if (ret != APP_ERR_OK) {
        LogError << GetModuleName() << " Init Error:" << ret;
        return ret;
    }
    //thread run todo
    threads_.emplace_back(&Module::Run, this);
    if (getFPS) {
        threads_.emplace_back(&Module::Fps, this);
    }

}

APP_ERROR Module::Stop() {
    status_ = RunMode::STOPPED;
    LogError << GetModuleName() << ":Stop";
    for (auto & t : threads_) {
        t.join();
    }
    LogError << GetModuleName() << ":Stop";
    auto ret = DeInit();
    if (ret != APP_ERR_OK) {
        LogError << GetModuleName() << " Init Error:" << ret;
        return ret;
    }
}

void Module::Run() {
    while (status_ == RunMode::RUNNING) {
        std::shared_ptr<void> input;
        std::shared_ptr<void> output;
        auto ret = GetData(input);
        if (ret != APP_ERR_OK) {
            LogError << GetModuleName() << " GetData Failed, ret=" << ret;
            continue;;
        }
        ret = Process(input);
        if (ret != APP_ERR_OK) {
            LogError << GetModuleName() << " Process Failed, ret=" << ret;
            break;
        }
    }
}

void Module::Fps() {
    while (status_ == RunMode::RUNNING) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        LogInfo << GetModuleName() << " FPS[" << count_ << "]";
        count_ = 0;
    } 
}

APP_ERROR Module::GetData(std::shared_ptr<void> &data) {
    return ModuleIOPortManager::GetInstance().GetData(inputPort_, data);
}

APP_ERROR Module::SendData(const std::shared_ptr<void> &data) {
    count_++;
    return ModuleIOPortManager::GetInstance().SendData(outputPort_, data);
}


void Module::SetInput(const std::string &inputName)
{
    inputPort_ = inputName;
}
void Module::SetOutput(const std::string &outputName)
{
    outputPort_ = outputName;
}


RunMode Module::Status() const {
    return status_;
}